package com.suke.czx.modules.wx.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.service.WxPayService;
import com.suke.czx.common.utils.DateUtils;
import com.suke.czx.common.utils.JsonResult;
import com.suke.czx.common.utils.RedisUtils;
import com.suke.czx.common.utils.UUIDS;
import com.suke.czx.modules.wx.config.WxMpConfiguration;
import com.suke.czx.modules.wx.config.WxPayProperties;
import com.suke.czx.modules.wx.util.CodeUtil;
import com.suke.czx.modules.wxadmin.entity.DkCourseEntity;
import com.suke.czx.modules.wxadmin.entity.DkDisEntity;
import com.suke.czx.modules.wxadmin.entity.DkReadPlanEntity;
import com.suke.czx.modules.wxadmin.entity.DkResourceEntity;
import com.suke.czx.modules.wxadmin.entity.DkUserEntity;
import com.suke.czx.modules.wxadmin.entity.DkUserInvEntity;
import com.suke.czx.modules.wxadmin.entity.DkUserOrderEntity;
import com.suke.czx.modules.wxadmin.service.DkCourseService;
import com.suke.czx.modules.wxadmin.service.DkDisService;
import com.suke.czx.modules.wxadmin.service.DkReadPlanService;
import com.suke.czx.modules.wxadmin.service.DkResourceService;
import com.suke.czx.modules.wxadmin.service.DkUserInvService;
import com.suke.czx.modules.wxadmin.service.DkUserOrderService;
import com.suke.czx.modules.wxadmin.service.DkUserService;

import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;

/**
 * @author Binary Wang
 */
@RestController
@RequestMapping("/wx/pay")
public class WxPayController extends BaseController {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private WxPayService wxPayService;
	@Autowired
	private DkCourseService dkCourseService;
	@Autowired
	private DkUserOrderService dkUserOrderService;
	@Autowired
	private DkResourceService dkResourceService;
	@Autowired
	private DkReadPlanService dkReadPlanService;
	@Autowired
	private DkUserService dkUserService;
	@Autowired
	private DkDisService dkDisService;
	@Autowired 
	private WxPayProperties wxPayProperties;
	
	@Autowired
	private DkUserInvService dkUserInvService;
	
	@Autowired
	private RedisUtils redisUtils;

	@RequestMapping("/createOrder")
	public String createOrder(String openid, @RequestParam(defaultValue = "1") Integer courseId, String dis) {
		// 查询配置活动信息，构建订单价格；
		DkCourseEntity course = dkCourseService.queryObject(courseId);
		DkDisEntity dkdis = null;
		boolean flag = false;
		if (null != dis && !dis.equals("")) {
			if(dis.equals(openid)){
				return new JsonResult(-1, "自己不能邀请自己支付！").toJson();
			}
			
			dkdis = dkDisService.queryObject(dis);
			if (null != dkdis) {
				course.setPriceOff(dkdis.getDisPrice());
			}
		}else{
			DkUserInvEntity user_inv = dkUserInvService.queryObject(openid);
			if(user_inv!=null){
				dis=user_inv.getInvUserId();
				flag=true;
			}
		}
		
		if(dis.equals("1")){
			DkUserInvEntity user_inv = dkUserInvService.queryObject(openid);
			if(user_inv!=null){
				dis=user_inv.getInvUserId();
				flag=true;
			}
		}
		
		DkUserEntity dkUser = dkUserService.queryObject(openid,false);
		if(dkUser.getState()==1){
			return new JsonResult(-1, "自己不能邀请自己支付！").toJson();
		}
		// 构建未处理订单，并且保存未处理订单
		DkUserOrderEntity order = new DkUserOrderEntity();
		order.setCourseId(course.getId());
		order.setOrderNo(CodeUtil.createOrderNo());
		order.setStatus(0);
		order.setTotalFee(course.getPriceOff());
		order.setUserId(openid);
		order.setUpdateTime(new Date());
		order.setPayReason(1);
		if (null == dkdis) {
			order.setDisId("0");
			if(dis!=null){
				order.setDisId(dis);
			}
		} else {
			order.setDisId(dkdis.getId());
		}
		dkUserOrderService.save(order);
		try {
			WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
			orderRequest.setBody(course.getCourseName());
			orderRequest.setOutTradeNo(order.getOrderNo());
			orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(order.getTotalFee().toPlainString()));// 元转成分
			orderRequest.setOpenid(openid);
			orderRequest.setSpbillCreateIp(CodeUtil.getIpAddr(getRequest()));
			orderRequest.setNotifyUrl(wxPayProperties.getNotifyBuy());
			orderRequest.setTradeType("JSAPI");
			if(flag){
				redisUtils.setObject("orderinv_"+order.getOrderNo(), openid, 3600);
			}
			return new JsonResult(200, "ok", wxPayService.createOrder(orderRequest)).toJson();
		} catch (Exception e) {
			logger.error("微信支付失败！订单号：{},原因:{}", order.getOrderNo(), e.getMessage());
			e.printStackTrace();
			return new JsonResult(-1, "微信支付异常").toJson();
		}
	}

	@RequestMapping("/createOrderRepair")
	public String createOrderRepair(String openid, @RequestParam(defaultValue = "1") Integer courseId, String dateStr) {

		// 检查对应日期是否打卡，避免重复支付打卡费用
		Map<String, String> parms = new HashMap<String, String>();
		parms.put("readDate", dateStr);
		parms.put("userId", openid);
		DkReadPlanEntity plan = dkReadPlanService.queryUserReadPlanByIdAndDate(parms);

		if (null == plan || plan.getStatus() == 1) {
			return new JsonResult(-1, "不需要补卡！").toJson();
		}
		if (plan.getResourceId() > 45) {
			return new JsonResult(-1, "45天之后不再提供补卡服务！").toJson();
		}
		// 查询配置活动信息，构建订单价格；
		DkCourseEntity course = dkCourseService.queryObject(courseId);

		// 构建未处理订单，并且保存未处理订单
		DkUserOrderEntity order = new DkUserOrderEntity();
		order.setCourseId(course.getId());
		order.setOrderNo(CodeUtil.createOrderNo());
		order.setStatus(0);

		order.setTotalFee(course.getReplenPrice().multiply(new BigDecimal(2)));

		order.setUserId(openid);
		order.setUpdateTime(new Date());
		order.setPayReason(2);
		dkUserOrderService.save(order);

		try {
			WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
			orderRequest.setBody(dateStr);
			orderRequest.setOutTradeNo(order.getOrderNo());
			orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(order.getTotalFee().toPlainString()));// 元转成分
			orderRequest.setOpenid(openid);
			orderRequest.setSpbillCreateIp(CodeUtil.getIpAddr(getRequest()));
			orderRequest.setNotifyUrl(wxPayProperties.getNotifyRepair());
			orderRequest.setTradeType("JSAPI");
			orderRequest.setAttach(dateStr);
			return new JsonResult(200, "ok", wxPayService.createOrder(orderRequest)).toJson();
		} catch (Exception e) {
			logger.error("微信支付失败！订单号：{},原因:{}", order.getOrderNo(), e.getMessage());
			e.printStackTrace();
			return new JsonResult(-1, "微信支付异常").toJson();
		}

	}

	@RequestMapping("/notify/Repair")
	@ResponseBody
	public String payNotifyRepair(HttpServletRequest request, HttpServletResponse response) {
		try {
			String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
			WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult);
			// 结果正确
			String orderId = result.getOutTradeNo();
			String tradeNo = result.getTransactionId();
			String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
			String dateStr = result.getAttach();
			Date date = new Date();
			// 自己处理订单的业务逻辑，需要判断订单是否已经支付过，否则可能会重复调用
			// 更新订单相关信息
			DkUserOrderEntity order = dkUserOrderService.queryObject(orderId);
			DkCourseEntity course = dkCourseService.queryObject(order.getCourseId());
			order.setStatus(1);
			order.setPayResult(tradeNo);
			order.setStartTime(DateUtils.format(new Date(), DateUtils.DATE_PATTERN));
			order.setEndTime(DateUtils.getDate(date, course.getPlanDays()));
			dkUserOrderService.update(order);

			Map<String, String> parms = new HashMap<String, String>();
			parms.put("readDate", dateStr);
			parms.put("userId", order.getUserId());

			DkReadPlanEntity plan = dkReadPlanService.queryUserReadPlanByIdAndDate(parms);
			plan.setStatus(2);
			plan.setReadtime(new Date());
			dkReadPlanService.update(plan);

			return WxPayNotifyResponse.success("处理成功!");
		} catch (Exception e) {
			logger.error("微信回调结果异常,异常原因{}", e.getMessage());
			return WxPayNotifyResponse.fail(e.getMessage());
		}
	}

	@RequestMapping("/notify/buy")
	@ResponseBody
	public String payNotify(HttpServletRequest request, HttpServletResponse response) {
		try {
			String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
			WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult);
			// 结果正确
			String orderId = result.getOutTradeNo();
			String tradeNo = result.getTransactionId();
			// String totalFee =
			// BaseWxPayResult.fenToYuan(result.getTotalFee());
			Date date = new Date();
			// 自己处理订单的业务逻辑，需要判断订单是否已经支付过，否则可能会重复调用
			// 更新订单相关信息
			DkUserOrderEntity order = dkUserOrderService.queryObject(orderId);
			if (order.getStatus() != 1) {
				DkCourseEntity course = dkCourseService.queryObject(order.getCourseId());
				order.setStatus(1);
				order.setPayResult(tradeNo);
				order.setStartTime(DateUtils.format(new Date(), DateUtils.DATE_PATTERN));
				order.setEndTime(DateUtils.getDate(date, course.getPlanDays()));
				dkUserOrderService.update(order);
			} else {
				return WxPayNotifyResponse.success("处理成功!");
			}

			// 1、获取构建计划相关数据，根据活动ID
			List<DkResourceEntity> dkrs = dkResourceService.querySysResourceByCourseId(order.getCourseId());
			// 更新用户信息

			DkUserEntity dkUser = dkUserService.queryObject(order.getUserId(),false);
			if (dkUser.getState() != 1) {
				dkUser.setOrdertime(date);
				dkUser.setState(1);
				dkUser.setStartTime(DateUtils.getDate(date, 0));
				dkUser.setEndTime(DateUtils.getDate(date, dkrs.size() - 1));
				dkUser.setCreatetime(new Date());
				dkUserService.update(dkUser);
			} else {
				return WxPayNotifyResponse.success("处理成功!");
			}
			// 构建用户打卡计划前，判断用户是否已经有学习计划了，如果已经有了，就不再构建直接返回

			List<DkReadPlanEntity> plans = dkReadPlanService.queryUserReadPlanById(dkUser.getOpenid());
			if (null == plans || plans.size() == 0) {
				// 2、构建学习计划
				plans = new ArrayList<DkReadPlanEntity>();
				for (int i = 0; i < dkrs.size(); i++) {
					DkReadPlanEntity plan = new DkReadPlanEntity();
					plan.setId(UUIDS.getUUID());
					plan.setCreatetime(new Date());
					plan.setReadDate(DateUtils.getDate(date, i));
					plan.setResourceId(dkrs.get(i).getId());
					Calendar cal = Calendar.getInstance();
					int h = cal.get(Calendar.HOUR_OF_DAY);
					plan.setStatus(0);
					if (h == 22 || h == 23) {
						if (i == 0) {
							plan.setStatus(3);
						}
					}
					plan.setUserId(order.getUserId());
					plan.setSendState(0);
					plans.add(plan);
				}
				dkReadPlanService.batchInsertUserReadPlan(plans);
			}

			new Thread(new Runnable() {
				public void run() {
					//"wx110e4b18284caf04"
					WxMpService wxMpService = WxMpConfiguration.getMpServices().get(wxPayProperties.getAppId());//
					// 处理领书奖励
					// 1、判断是否有邀请者
					if (order.getDisId() != null && order.getDisId().length() > 20) {
						DkUserEntity inv_user = dkUserService.queryObject(order.getDisId(),false);
						if (null != inv_user) {
							//2、给邀请者赠送书币
							
							String inv_flag = redisUtils.getObject("orderinv_"+order.getOrderNo());
							String tmp_str = "1个";
							String tmp_str1 = "推荐";
							if(null==inv_flag){
								dkUserService.addCoin(inv_user.getOpenid());
							}else{
								dkUserService.addCoin5(inv_user.getOpenid());
								tmp_str = "0.5个";
								tmp_str1 = "朋友圈";
							}
							
							//3、给被邀请者送书币
							//dkUserService.addCoin(order.getUserId());
							
							// 发送模板消息 --- 给邀请成功的人
							try {
								WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder().toUser(inv_user.getOpenid())
										.templateId(wxPayProperties.getTidRecommend()).build();
								templateMessage.addData(new WxMpTemplateData("first", "您好！您的朋友通过您的"+tmp_str1+"加入诗词精读，您获得"+tmp_str+"领书币！\r\n", "#000000"));
								templateMessage.addData(new WxMpTemplateData("keyword1", dkUser.getNickname(), "#000000"));
								templateMessage.addData(new WxMpTemplateData("keyword2", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN), "#000000"));
								templateMessage.addData(
										new WxMpTemplateData("remark", "请点此继续邀请好友报名！\r\n", "#000000"));
								templateMessage.setUrl(wxPayProperties.getUrlRecommend().replace("{{openid}}", inv_user.getOpenid()));
								wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
							} catch (WxErrorException e) {
								e.printStackTrace();
							}
						}
					}

					// 演示10s秒钟发送模板消息
					try {
						
						WxMpUser wxMpUser = wxMpService.getUserService().userInfo(order.getUserId());
						if (!wxMpUser.getSubscribe()) {
							return;
						}
						// 发送模板消息 --- 给订购成功的人
						WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder().toUser(order.getUserId())
								.templateId(wxPayProperties.getTidBuySuccess()).build();
						templateMessage.addData(new WxMpTemplateData("first", "您已成功订购以下课程\r\n\r\n", "#000000"));
						templateMessage.addData(new WxMpTemplateData("keyword1", "《精读诗词·210天学习计划》", "#000000"));
						templateMessage.addData(new WxMpTemplateData("keyword2", dkUser.getStartTime(), "#000000"));
						templateMessage.addData(new WxMpTemplateData("keyword3", "长期有效，可以反复听", "#000000"));
						templateMessage.addData(
								new WxMpTemplateData("remark", "点击下方『今日阅读』即刻开启今天的课程，记得学习哟~\r\n\r\n↓↓↓", "#000000"));
						
						wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}).start();
			return WxPayNotifyResponse.success("处理成功!");
		} catch (Exception e) {
			logger.error("微信回调结果异常,异常原因{}", e.getMessage());
			return WxPayNotifyResponse.fail(e.getMessage());
		}
	}

}